/// 分片格式处理trait
pub trait SegmentFormat: Send + Sync + std::fmt::Debug {
    /// 获取格式标识符
    fn format_id(&self) -> &'static str;
    
    /// 获取文件扩展名
    fn extension(&self) -> &'static str;
    
    /// 获取进度条显示图标
    fn progress_icon(&self) -> &'static str;
    
    /// 获取格式描述
    fn description(&self) -> &'static str;
    
    /// 检查URL是否匹配此格式
    fn matches_url(&self, url: &str) -> bool;
    
    /// 生成本地文件名
    fn generate_filename(&self, index: usize) -> String {
        format!("{:06}.{}", index, self.extension())
    }
    
    /// 是否为视频格式
    fn is_video(&self) -> bool {
        false
    }
    
    /// 是否为图片格式
    fn is_image(&self) -> bool {
        false
    }
}

/// TS视频格式
#[derive(Debug, Clone)]
pub struct TsFormat;

impl SegmentFormat for TsFormat {
    fn format_id(&self) -> &'static str { "ts" }
    fn extension(&self) -> &'static str { "ts" }
    fn progress_icon(&self) -> &'static str { "📥 TS" }
    fn description(&self) -> &'static str { "MPEG-2 Transport Stream" }
    
    fn matches_url(&self, url: &str) -> bool {
        url.ends_with(".ts")
    }
    
    fn is_video(&self) -> bool { true }
}

/// M4S视频格式
#[derive(Debug, Clone)]
pub struct M4sFormat;

impl SegmentFormat for M4sFormat {
    fn format_id(&self) -> &'static str { "m4s" }
    fn extension(&self) -> &'static str { "m4s" }
    fn progress_icon(&self) -> &'static str { "📺 M4S" }
    fn description(&self) -> &'static str { "MPEG-4 Segment" }
    
    fn matches_url(&self, url: &str) -> bool {
        url.ends_with(".m4s")
    }
    
    fn is_video(&self) -> bool { true }
}

/// JPEG图片格式
#[derive(Debug, Clone)]
pub struct JpegFormat;

impl SegmentFormat for JpegFormat {
    fn format_id(&self) -> &'static str { "jpeg" }
    fn extension(&self) -> &'static str { "jpeg" }
    fn progress_icon(&self) -> &'static str { "📷 IMG" }
    fn description(&self) -> &'static str { "JPEG Image" }
    
    fn matches_url(&self, url: &str) -> bool {
        url.ends_with(".jpeg") || url.ends_with(".jpg")
    }
    
    fn is_image(&self) -> bool { true }
}

/// PNG图片格式
#[derive(Debug, Clone)]
pub struct PngFormat;

impl SegmentFormat for PngFormat {
    fn format_id(&self) -> &'static str { "png" }
    fn extension(&self) -> &'static str { "png" }
    fn progress_icon(&self) -> &'static str { "🖼️ PNG" }
    fn description(&self) -> &'static str { "PNG Image" }
    
    fn matches_url(&self, url: &str) -> bool {
        url.ends_with(".png")
    }
    
    fn is_image(&self) -> bool { true }
}

/// MP4视频格式
#[derive(Debug, Clone)]
pub struct Mp4Format;

impl SegmentFormat for Mp4Format {
    fn format_id(&self) -> &'static str { "mp4" }
    fn extension(&self) -> &'static str { "mp4" }
    fn progress_icon(&self) -> &'static str { "🎥 MP4" }
    fn description(&self) -> &'static str { "MPEG-4 Video" }
    
    fn matches_url(&self, url: &str) -> bool {
        url.ends_with(".mp4")
    }
    
    fn is_video(&self) -> bool { true }
}

/// 格式检测器
pub struct FormatDetector {
    formats: Vec<Box<dyn SegmentFormat>>,
}

impl FormatDetector {
    pub fn new() -> Self {
        Self {
            formats: vec![
                Box::new(TsFormat),
                Box::new(M4sFormat),
                Box::new(JpegFormat),
                Box::new(PngFormat),
                Box::new(Mp4Format),
            ],
        }
    }
    
    /// 根据URL检测格式
    pub fn detect_format(&self, url: &str) -> Option<&dyn SegmentFormat> {
        self.formats.iter()
            .find(|format| format.matches_url(url))
            .map(|format| format.as_ref())
    }
    
    /// 获取默认格式（TS）
    pub fn default_format(&self) -> &dyn SegmentFormat {
        &*self.formats[0] // TsFormat
    }
    
    /// 获取所有支持的格式
    pub fn supported_formats(&self) -> Vec<&str> {
        self.formats.iter()
            .map(|format| format.format_id())
            .collect()
    }
}

impl Default for FormatDetector {
    fn default() -> Self {
        Self::new()
    }
}

impl std::fmt::Debug for FormatDetector {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("FormatDetector")
            .field("supported_formats", &self.supported_formats())
            .finish()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_ts_format() {
        let format = TsFormat;
        assert_eq!(format.format_id(), "ts");
        assert_eq!(format.extension(), "ts");
        assert_eq!(format.progress_icon(), "📥 TS");
        assert!(format.matches_url("segment001.ts"));
        assert!(!format.matches_url("segment001.jpeg"));
        assert!(format.is_video());
        assert!(!format.is_image());
    }

    #[test]
    fn test_jpeg_format() {
        let format = JpegFormat;
        assert_eq!(format.format_id(), "jpeg");
        assert_eq!(format.extension(), "jpeg");
        assert_eq!(format.progress_icon(), "📷 IMG");
        assert!(format.matches_url("image001.jpeg"));
        assert!(format.matches_url("image001.jpg"));
        assert!(!format.matches_url("image001.png"));
        assert!(!format.is_video());
        assert!(format.is_image());
    }

    #[test]
    fn test_format_detector() {
        let detector = FormatDetector::new();
        
        // 测试TS格式检测
        let ts_format = detector.detect_format("segment001.ts").unwrap();
        assert_eq!(ts_format.format_id(), "ts");
        
        // 测试JPEG格式检测
        let jpeg_format = detector.detect_format("image001.jpeg").unwrap();
        assert_eq!(jpeg_format.format_id(), "jpeg");
        
        // 测试未知格式
        let unknown = detector.detect_format("unknown.xyz");
        assert!(unknown.is_none());
        
        // 测试默认格式
        let default = detector.default_format();
        assert_eq!(default.format_id(), "ts");
        
        // 测试支持的格式列表
        let supported = detector.supported_formats();
        assert!(supported.contains(&"ts"));
        assert!(supported.contains(&"jpeg"));
        assert!(supported.contains(&"png"));
    }

    #[test]
    fn test_filename_generation() {
        let ts_format = TsFormat;
        assert_eq!(ts_format.generate_filename(1), "000001.ts");
        assert_eq!(ts_format.generate_filename(999), "000999.ts");
        
        let jpeg_format = JpegFormat;
        assert_eq!(jpeg_format.generate_filename(1), "000001.jpeg");
    }
}